package net.realsee.gcl.schedule;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import net.realsee.common.enums.wcs.ccs.GclCcsLocationStatusEnum;
import net.realsee.common.enums.wcs.ccs.GclLocationTaskStatusEnum;
import net.realsee.common.enums.wcs.charact.WcsCharactEnum;
import net.realsee.common.enums.wcs.order.OrderStatusEnums;
import net.realsee.common.enums.wcs.order.OrderTypeEnums;
import net.realsee.common.utils.PlcUtil;
import net.realsee.domain.wcs.device.bo.PlcReadWriteBo;
import net.realsee.domain.wcs.rcs.hik.HikRcsOperateResult;
import net.realsee.domain.wcs.warehouse.WcsWarehouseLocation;
import net.realsee.domain.wcs.work.WcsOrderHeader;
import net.realsee.framework.plc.PlcOperateResult;
import net.realsee.gcl.service.IGclLocationExtendService;
import net.realsee.gcl.service.IGclMesService;
import net.realsee.service.wcs.device.IWcsPlcTagService;
import net.realsee.service.wcs.rcs.hik.IHikV4Service;
import net.realsee.service.wcs.warehouse.IWcsWarehouseLocationService;
import net.realsee.service.wcs.work.IWcsOrderDetailService;
import net.realsee.service.wcs.work.IWcsOrderHeaderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 定时任务调度
 *
 * @author realsee
 */
@Slf4j
@Component("wcsJob")
public class WcsJob {

    @Autowired
    private IHikV4Service hikV4Service;
    @Autowired
    private IWcsOrderHeaderService orderHeaderService;
    @Autowired
    private IWcsOrderDetailService orderDetailService;
    @Autowired
    private IWcsWarehouseLocationService locationService;
    @Autowired
    private IWcsPlcTagService plcTagService;
    @Autowired
    private IGclMesService mesService;
    @Autowired
    private IGclLocationExtendService locationExtendService;

    public void handleWaitingTask() {
        // 查询出处于等待点位上的任务集合
        List<WcsOrderHeader> orderHeaderList = orderHeaderService.listWaitingTask();

        for (WcsOrderHeader orderHeader : orderHeaderList) {
            try {
                // 查询出该单据的终点位置
                String endLocation = orderDetailService.getEndLocationByOrderNoAndOrderType(orderHeader.getOrderNo(), OrderTypeEnums.BUSINESS.getCode());
                if (StrUtil.equalsAnyIgnoreCase(endLocation, "04TJGZ001")) {
                    // 当为脱胶下工装库位时，需要读取的是PLC状态
                    String wcsRequestInTag = locationService.getValueByLocationAndCharact(endLocation, WcsCharactEnum.ARM_ALLOW_IN);
                    if (StrUtil.isNotBlank(wcsRequestInTag)) {
                        PlcReadWriteBo plcReadWriteBo = plcTagService.getByTagCode(wcsRequestInTag);
                        if (ObjectUtil.isNotNull(plcReadWriteBo)) {
                            PlcOperateResult operateResult = PlcUtil.read(plcReadWriteBo);
                            if (StrUtil.equalsAnyIgnoreCase("true", operateResult.content)) {
                                // PLC 允许进站
                                // 可以继续执行
                                HikRcsOperateResult hikRcsOperateResult = hikV4Service.taskContinue(orderHeader.getOrderNo(), null);
                                if (ObjectUtil.isNotNull(hikRcsOperateResult) && hikRcsOperateResult.isSuccess()) {
                                    orderHeader.setOrderStatus(OrderStatusEnums.STARTED.getCode());
                                    orderHeaderService.updateById(orderHeader);
                                }
                            }
                        }
                    }
                } else {
                    // 查询中控状态（10则可进入）
                    if (ObjectUtil.equal(locationExtendService.getCcsLocationStatus(endLocation), GclCcsLocationStatusEnum.EMPTY.getCode())) {
                        // 可以继续执行
                        HikRcsOperateResult hikRcsOperateResult = hikV4Service.taskContinue(orderHeader.getOrderNo(), null);
                        if (ObjectUtil.isNotNull(hikRcsOperateResult) && hikRcsOperateResult.isSuccess()) {
                            orderHeader.setOrderStatus(OrderStatusEnums.STARTED.getCode());
                            orderHeaderService.updateById(orderHeader);
                        }
                    }
                }
            } catch (Exception e) {
                log.error("处理等待任务异常，任务号={}。", orderHeader.getOrderNo(), e);
            }
        }
    }

    /**
     * 处理脱胶下工装库位离站申请
     */
    public void handleTJGZOutRequest() {
        WcsWarehouseLocation tjgzLocation = locationService.getByLocation("04TJGZ001");
        Integer wcsLocationTaskStatus = locationExtendService.getWcsLocationTaskStatus(tjgzLocation.getLocation());
        if (ObjectUtil.notEqual(wcsLocationTaskStatus, GclLocationTaskStatusEnum.IN_BIN.getCode())) {
            return;
        }

        // 判断是否已经通知过mes
        String wcsHasIn = locationService.getValueByLocationAndCharact(tjgzLocation.getLocation(), WcsCharactEnum.WCS_HAS_IN);
        if (StrUtil.isNotBlank(wcsHasIn)) {
            PlcReadWriteBo plcReadWriteBo = plcTagService.getByTagCode(wcsHasIn);
            if (ObjectUtil.isNotNull(plcReadWriteBo)) {
                PlcOperateResult operateResult = PlcUtil.read(plcReadWriteBo);
                if (!StrUtil.equalsIgnoreCase(operateResult.content, "true")) {
                    return;
                }
            }
        }
        // PLC 允许离站
        String wcsRequestInTag = locationService.getValueByLocationAndCharact(tjgzLocation.getLocation(), WcsCharactEnum.ARM_ALLOW_OUT);
        if (StrUtil.isNotBlank(wcsRequestInTag)) {
            PlcReadWriteBo plcReadWriteBo = plcTagService.getByTagCode(wcsRequestInTag);
            if (ObjectUtil.isNotNull(plcReadWriteBo)) {
                PlcOperateResult operateResult = PlcUtil.read(plcReadWriteBo);
                if (StrUtil.equalsIgnoreCase(operateResult.content, "true")) {
                    // PLC 允许离站
                    // 调MES，脱胶下工装完成接口
                    mesService.tjMachineToolOutToMes("04TJGZ001");
                    // 更新到站通知为false
                    wcsRequestInTag = locationService.getValueByLocationAndCharact(tjgzLocation.getLocation(), WcsCharactEnum.WCS_HAS_IN);
                    if (StrUtil.isNotBlank(wcsRequestInTag)) {
                        plcReadWriteBo = plcTagService.getByTagCode(wcsRequestInTag);
                        if (ObjectUtil.isNotNull(plcReadWriteBo)) {
                            plcReadWriteBo.setToWriteValue("false");
                            try {
                                PlcUtil.write(plcReadWriteBo);
                            } catch (Exception e) {
                                log.error("脱胶下工装，写到站通知标识失败。");
                            }
                        }
                    }
                    // 更新离站申请为false
                    wcsRequestInTag = locationService.getValueByLocationAndCharact(tjgzLocation.getLocation(), WcsCharactEnum.WCS_REQUEST_OUT);
                    if (StrUtil.isNotBlank(wcsRequestInTag)) {
                        plcReadWriteBo = plcTagService.getByTagCode(wcsRequestInTag);
                        if (ObjectUtil.isNotNull(plcReadWriteBo)) {
                            plcReadWriteBo.setToWriteValue("false");
                            try {
                                PlcUtil.write(plcReadWriteBo);
                            } catch (Exception e) {
                                log.error("脱胶下工装，写离站申请标识失败。");
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 处理脱胶下工装库位PLC心跳
     */
    private final AtomicBoolean heartbeat = new AtomicBoolean();

    public void handleTJGZPlcHeartbeat() {
        // 获取04TJGZ001库位对应的写心跳点位
        PlcReadWriteBo plcReadWriteBo = plcTagService.getByTagCode("WCS_TJ01_DEVICE_HEARTBEAT");
        plcReadWriteBo.setToWriteValue(StrUtil.toString(heartbeat.get()));
        PlcUtil.write(plcReadWriteBo);
        heartbeat.set(!heartbeat.get());
    }
}
